package com.rules.admin.utils;

import cn.hutool.core.collection.CollectionUtil;
import com.gillion.grule.client.utils.ContextHolder;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;

import com.rules.admin.domain.IRole;
import com.rules.admin.domain.ITable;
import com.rules.admin.domain.IUser;
import com.rules.admin.domain.UserInfoCollector;
import com.rules.admin.service.UserService;

import org.springframework.lang.Nullable;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

public final class UserUtils {
    public static final String anonymousUsername = "匿名用户";
    public static final String ANONYMOUS_ROLE_ID = "ba98c88eb2f14632948d189cd41e4518";
    public static final IUser anonymousUser = new IUser() {
        public String getUserId() {
            return "";
        }

        public Set<String> getHasPermissionUrlPatterns() {
            UserService userService = (UserService)ContextHolder.getBean(UserService.class);
            return Sets.newHashSet(userService.getAnonymousPermissionUrlPatterns());
        }

        public Collection<IRole> getAuthorities() {
            return Lists.newArrayList();
        }

        public void setAuthorities(Iterable<? extends IRole> roles) {
        }

        public String getPassword() {
            return null;
        }

        public String getUsername() {
            return "匿名用户";
        }

        public boolean isAccountNonExpired() {
            return true;
        }

        public boolean isAccountNonLocked() {
            return true;
        }

        public boolean isCredentialsNonExpired() {
            return true;
        }

        public boolean isEnabled() {
            return true;
        }

        public boolean equals(Object o) {
            if (this == o) {
                return true;
            } else if (!(o instanceof IUser)) {
                return false;
            } else {
                IUser that = (IUser)o;
                return Objects.equal(this.getUsername(), that.getUsername());
            }
        }

        public int hashCode() {
            return Objects.hashCode(new Object[]{this.getUsername()});
        }

        public Collection<ITable> getPermissionTables() {
            UserService userService = (UserService) ContextHolder.getBean(UserService.class);
            return userService.getAnonymousDataPermissionTables();
        }
    };

    public UserUtils() {
    }

    public static IUser getCurrentLoginUser() {
        UserInfoCollector userInfoCollector = (UserInfoCollector)ContextHolder.getBean(UserInfoCollector.class);
        IUser user = userInfoCollector.getCurrentLoginUser();
        return user == null ? anonymousUser : user;
    }

    public static EffectiveUser getCurrentEffectiveLoginUser() {
        return UserUtils.EffectiveUser.from(getCurrentLoginUser());
    }

    public static boolean isAnonymous() {
        return anonymousUser.equals(getCurrentLoginUser());
    }

    public static final class EffectiveUser implements IUser {
        private IUser originalUser;
        private Set<AntPathRequestMatcher> hasPermissionAntPathRequestMatcher = Sets.newHashSet();

        private EffectiveUser(IUser user) {
            this.originalUser = user;
            if (CollectionUtil.isNotEmpty(this.originalUser.getHasPermissionUrlPatterns())) {
                Iterables.addAll(this.hasPermissionAntPathRequestMatcher, Iterables.transform(this.originalUser.getHasPermissionUrlPatterns(), new Function<String, AntPathRequestMatcher>() {
                    @Nullable
                    public AntPathRequestMatcher apply(String hasPermissionUrlPattern) {
                        return new AntPathRequestMatcher(hasPermissionUrlPattern);
                    }
                }));
            }

        }

        public static EffectiveUser from(IUser user) {
            return new EffectiveUser(user);
        }

        public final boolean matches(final HttpServletRequest request) {
            return Iterables.any(this.hasPermissionAntPathRequestMatcher, new Predicate<AntPathRequestMatcher>() {
                public boolean apply(@Nullable AntPathRequestMatcher input) {
                    return input.matches(request);
                }
            });
        }

        public Object getUserId() {
            return this.originalUser.getUserId();
        }

        public Collection<IRole> getAuthorities() {
            return this.originalUser.getAuthorities();
        }

        public String getPassword() {
            return this.originalUser.getPassword();
        }

        public String getUsername() {
            return this.originalUser.getUsername();
        }

        public boolean isAccountNonExpired() {
            return this.originalUser.isAccountNonExpired();
        }

        public boolean isAccountNonLocked() {
            return this.originalUser.isAccountNonLocked();
        }

        public boolean isCredentialsNonExpired() {
            return this.originalUser.isCredentialsNonExpired();
        }

        public boolean isEnabled() {
            return this.originalUser.isEnabled();
        }

        public void setAuthorities(Iterable<? extends IRole> roles) {
            this.originalUser.setAuthorities(roles);
        }

        public Set<String> getHasPermissionUrlPatterns() {
            return this.originalUser.getHasPermissionUrlPatterns();
        }

        public Set<AntPathRequestMatcher> getHasPermissionAntPathRequestMatcher() {
            return this.hasPermissionAntPathRequestMatcher;
        }

        public Collection<ITable> getPermissionTables() {
            return this.originalUser.getPermissionTables();
        }
    }
}